﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text.RegularExpressions;
using GS1.Tools.Extender;
using System.Windows.Forms;

namespace SegIdenMovil
{
    public static class Utilitario
    {
        #region --- Serializacion y Deserializacion XML ---
        /// <summary>
        /// Serializar a XML (Personalizado) un objeto cualquiera
        /// </summary>
        /// <param name="obj">Objeto a serializar</param>
        /// <param name="encoding">Codificacion del objeto</param>
        /// <returns>Objeto serializado en formato XML</returns>
        public static string SerializarToXml(this object objetoASerializar, Encoding encoding)
        {   /*
            string XmlizedString = null;

            try
            {               
                /*
                XmlSerializer xs = new XmlSerializer(obj.GetType());
                //create an instance of the MemoryStream class since we intend to keep the XML string 
                //in memory instead of saving it to a file.
                MemoryStream memoryStream = new MemoryStream();
                //XmlTextWriter - fast, non-cached, forward-only way of generating streams or files 
                //containing XML data
                XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, encoding);
                //Serialize emp in the xmlTextWriter
                xs.Serialize(xmlTextWriter, obj);
                //Get the BaseStream of the xmlTextWriter in the Memory Stream
                memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
                //Convert to array
                XmlizedString = PersonalizadoByteArrayToString(memoryStream.ToArray(), encoding);
                */
            /*
            XmlSerializer xs = new XmlSerializer(obj.GetType());

            XmlSerializerNamespaces nmsp = new XmlSerializerNamespaces();
            nmsp.Add(string.Empty, string.Empty);

            StringWriterPersonalizado writer = new StringWriterPersonalizado();
            writer.EncodingActual = encoding;
            writer.NewLine = string.Empty;

            xs.Serialize(writer, obj, nmsp);
            XmlizedString = writer.ToString();
            return XmlizedString;
        }
        catch
        {
            return string.Empty;
        }
        */
            try
            {
                XmlSerializer xmlSerializer = new XmlSerializer(objetoASerializar.GetType());

                XmlSerializerNamespaces nmsp = new XmlSerializerNamespaces();
                nmsp.Add(string.Empty, string.Empty);

                using (MemoryStream memoryStream = new MemoryStream())
                {
                    XmlWriterSettings settings = new XmlWriterSettings();
                    settings.Encoding = encoding;
                    settings.Indent = false; // true;
                    settings.IndentChars = string.Empty; // "\t";
                    settings.NewLineChars = string.Empty; // Environment.NewLine;
                    settings.ConformanceLevel = ConformanceLevel.Document;
                    settings.OmitXmlDeclaration = false;

                    using (XmlWriter writer = XmlTextWriter.Create(memoryStream, settings))
                    {
                        xmlSerializer.Serialize(writer, objetoASerializar, nmsp);
                    }

                    string xml = encoding.GetString(memoryStream.ToArray(), 0, memoryStream.ToArray().Length);
                    xml = xml.Substring(0, 1).Equals("<") ? xml : xml.Substring(1);

                    return xml;
                }
            }
            catch
            {
                return string.Empty;
            }

        }

        /// <summary>
        /// Serializar a XML (Personalizado) un objeto cualquiera
        /// </summary>
        /// <param name="obj">objeto a serializar</param>
        /// <returns>Objeto serializado en formato XML</returns>
        public static string SerializarToXml(this object objetoASerializar)
        {
            return SerializarToXml(objetoASerializar, ParametrosAplicacion.EncodingAplicacion);
        }

        /// <summary>
        /// Deserializar un XML a un objeto T
        /// </summary>
        /// <typeparam name="T">Tipo del objeto a retornar</typeparam>
        /// <param name="xmlSerializado">Trama en formato XML</param>
        /// <param name="encoding">Codificacion de la trama</param>
        /// <returns>Objeto resultado</returns>
        public static T DeserializarTo<T>(this string xmlSerializado, Encoding encoding)
        {   /*
            try
            {
                using (MemoryStream memoryStream = new MemoryStream(PersonalizadoStringToByteArray(xmlSerializado, encoding)))
                {
                    using (XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, encoding))
                    {
                        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));

                        return (T)xmlSerializer.Deserialize(memoryStream);
                    }
                }
            }
            catch
            {
                return default(T);
            }
            */

            try
            {
                XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));

                using (MemoryStream memoryStream = new MemoryStream(encoding.GetBytes(xmlSerializado)))
                {
                    return (T)xmlSerializer.Deserialize(memoryStream);
                }
            }
            catch
            {
                return default(T);
            }
        }

        /// <summary>
        /// Deserializar un XML a un objeto T
        /// </summary>
        /// <typeparam name="T">Tipo del objeto a retornar</typeparam>
        /// <param name="xmlSerializado">Trama en formato XML</param>
        /// <returns>Objeto resultado</returns>
        public static T DeserializarTo<T>(this string xmlSerializado)
        {
            return DeserializarTo<T>(xmlSerializado, ParametrosAplicacion.EncodingAplicacion);
        }

        /// <summary>
        /// Convierte una trama a una arreglo de bytes
        /// </summary>
        /// <param name="xml">Trama a convertir</param>
        /// <param name="encoding">Codificacion de la trama</param>
        /// <returns>Arreglo de bytes</returns>
        public static Byte[] PersonalizadoStringToByteArray(string xml, Encoding encoding)
        {
            return encoding.GetBytes(xml);
        }

        /// <summary>
        /// Convierte una trama a una arreglo de bytes
        /// </summary>
        /// <param name="xml">Trama a convertir</param>
        /// <returns>Arreglo de bytes</returns>
        public static Byte[] PersonalizadoStringToByteArray(string xml)
        {
            return PersonalizadoStringToByteArray(xml, ParametrosAplicacion.EncodingAplicacion);
        }
        #endregion

        #region --- Tratamiento de Imagenes ---
        /// <summary>
        /// Serializa una imagen a base64
        /// </summary>
        /// <param name="image">Imagen a serializar</param>
        /// <param name="format">Formato de la imagen</param>
        /// <returns>Trama serializada</returns>
        public static string imageToBase64(this Image image, ImageFormat format)
        {
            string base64String = string.Empty;

            if (image != null)
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    // Convert Image to byte[]
                    image.Save(ms, format);
                    byte[] imageBytes = ms.ToArray();

                    // Convert byte[] to Base64 String
                    base64String = Convert.ToBase64String(imageBytes);
                }
            }

            return base64String;
        }

        /// <summary>
        /// Deserializa una trama a base64 a imagen
        /// </summary>
        /// <param name="base64String">Trama en base64</param>
        /// <returns>Imagen obtenida</returns>
        public static Image base64ToImage(this string base64String)
        {
            Image image = null;

            if ((base64String != null) && (!base64String.Equals(string.Empty)))
            {
                // Convert Base64 String to byte[]
                byte[] imageBytes = Convert.FromBase64String(base64String);
                MemoryStream ms = new MemoryStream(imageBytes, 0,
                  imageBytes.Length);

                // Convert byte[] to Image
                ms.Write(imageBytes, 0, imageBytes.Length);
                image = new Bitmap(ms);
            }

            return image;
        }
        #endregion

        #region --- Formateo de cadenas ---
        /// <summary>
        /// Extensor: Que permite validar si la cadena enviada es del tipo Correo
        /// </summary>
        /// <param name="dataCorreo">texto a validar</param>
        /// <returns>True o False</returns>
        public static bool EsFormatoCorreo(this string dataCorreo)
        {
            Regex regex = null;
            regex = new Regex(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$");

            //\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b
            return regex.IsMatch(dataCorreo);
        }

        /// <summary>
        /// Extensor: Que permite validar si cadena enviada es del tipo Decimal
        /// </summary>
        /// <param name="dataDecimal">texto a validar</param>
        /// <returns>True o False</returns>
        public static bool EsFormatoDecimal(this string dataDecimal)
        {
            Regex regex = null;
            regex = new Regex(@"[-+]?[0-9]*\.?[0-9]*");

            return regex.IsMatch(dataDecimal);
        }

        /// <summary>
        /// Extensor: Que permite validar si cadena enviada es del tipo Entero con signo
        /// </summary>
        /// <param name="dataEntero">texto a validar</param>
        /// <returns>True o False</returns>
        public static bool EsEnteroConSigno(this string dataEntero)
        {
            Regex regex = null;
            regex = new Regex(@"[-+]?[0-9]*");

            return regex.IsMatch(dataEntero);
        }

        /// <summary>
        /// Extensor: Que permite validar si cadena enviada es del tipo Entero sin signo
        /// </summary>
        /// <param name="dataEntero">texto a validar</param>
        /// <returns>True o False</returns>
        public static bool EsEnteroSinSigno(this string dataEntero)
        {
            Regex regex = null;
            regex = new Regex(@"[0-9]*");

            return regex.IsMatch(dataEntero);
        }
        #endregion

        #region --- Conversion Cadenas ---
        /// <summary>
        /// Extensor: Que permite convertir una cadena a Entero
        /// </summary>
        /// <param name="data">cadena a convertir</param>
        /// <returns>Valor Entero</returns>
        public static int ToEntero(this string data)
        {
            int numero = 0;
            numero = Convert.ToInt32(data);
            return numero;
        }

        /// <summary>
        /// Extensor: Que permite convertir una cadena a Double
        /// </summary>
        /// <param name="data">cadena a convertir</param>
        /// <returns>Valor Double</returns>
        public static double ToDouble(this string data)
        {
            double numero = 0;
            numero = Convert.ToDouble(data);
            return numero;
        }

        /// <summary>
        /// Extensor: Que permite convertir una cadena a Entero
        /// </summary>
        /// <param name="data">cadena a convertir</param>
        /// <returns>Valor Decimal</returns>
        public static decimal ToDecimal(this string data)
        {
            decimal numero = 0;
            numero = Convert.ToDecimal(data);
            return numero;
        }
        #endregion

        #region --- Metodos de Encriptacion y Desencriptacion ---
        /// <summary>
        /// Funcion que permite de encriptar una cadena
        /// </summary>
        /// <param name="data">Cadena a ser desencriptada</param>
        /// <returns>Retorna Cadena desencriptada</returns>
        public static string Desencriptar(this string data)
        {
            byte[] bytes = Convert.FromBase64String(data);
            return Encoding.Default.GetString(bytes, 0, bytes.Length);
        }

        /// <summary>
        /// Funcion que permite encriptar una cadena
        /// </summary>
        /// <param name="data">Cadena a encriptar</param>
        /// <returns>Retorna Cadena encriptada</returns>
        public static string Encriptar(this string data)
        {
            byte[] bytes = Encoding.Default.GetBytes(data);
            return Convert.ToBase64String(bytes, 0, bytes.Length);
        }

        #endregion

        #region --- Extender Controles ---
        public static void aplicarEstiloGrilla(ListView lvwListado, Form frmFormulario)
        {
            ListViewExv estiloListView = null;

            lvwListado.FullRowSelect = true;

            estiloListView = new ListViewExv(lvwListado, frmFormulario);
            estiloListView.SetGridLines();
        }

        public static void aplicarEstiloGrilla(ListView lvwListado, Form frmFormulario, EventHandler dobleClickListado)
        {
            ListViewExv estiloListView = null;

            lvwListado.FullRowSelect = true;

            estiloListView = new ListViewExv(lvwListado, frmFormulario);
            estiloListView.SetGridLines();
            estiloListView.DoubleClick += dobleClickListado;
        }
        #endregion
    }

    public class StringWriterPersonalizado : StringWriter
    {
        public Encoding EncodingActual { get; set; }

        public override Encoding Encoding
        {
            get { return EncodingActual; }
        }
    }
}
